package commom;

import interfaces.kernel.JCL_skeleton;
import interfaces.kernel.JCL_task;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class JCL_skeletonImpl implements JCL_skeleton{
	
	private Map<String, Class<?>> cache;
	private Map<String, Object> cache1;
	
	private JCL_skeletonImpl(){
		this.cache = new ConcurrentHashMap<String, Class<?>>();
		this.cache1 = new ConcurrentHashMap<String, Object>();
	}
	
	private Object instantiate(JCL_task task, Class<?> c) throws Exception{
		
		if(task.getObjectMethod()!=null){
				Class<?> c1 = this.cache.get(task.getObjectName());
				if(c1==null){
					c1 = task.getObjectClass();
					this.cache.put(task.getObjectName(), c1);
				}
				Method[] ms = c1.getMethods();
				for(Method m : ms)
					if(m.getName().equals(task.getObjectMethod())){
						if(task.getMethodParameters()==null){
							if (m.getParameterTypes().length==0){
						
								Object instance = this.cache1.get(task.getObjectName());
								if(instance==null){
									instance = c1.newInstance();
									this.cache1.put(task.getObjectName(), instance);
								}
								return m.invoke(instance, task.getMethodParameters());
							}
						}else if (m.getParameterTypes().length==task.getMethodParameters().length){
							Object instance = this.cache1.get(task.getObjectName());
							if(instance==null){
								instance = c1.newInstance();
								this.cache1.put(task.getObjectName(), instance);
							}
							return m.invoke(instance, task.getMethodParameters());
						}
					}	
				return null;
				
		}else{
				Method[] ms = c.getMethods();
				for(Method m : ms)
					if(m.getName().equals("execute")){
						if(task.getMethodParameters()==null){
							if(m.getParameterTypes().length==0){
								Object instance = this.cache1.get(task.getObjectName());
								if(instance==null){
									instance = c.newInstance();
									this.cache1.put(task.getObjectName(), instance);
								}
								return m.invoke(instance, task.getMethodParameters());
							}
						}else if (m.getParameterTypes().length==task.getMethodParameters().length){
							Object instance = this.cache1.get(task.getObjectName());
							if(instance==null){
								instance = c.newInstance();
								this.cache1.put(task.getObjectName(), instance);
							}
							return m.invoke(instance, task.getMethodParameters());
						}
					}	
				
				return null;
		}
		
		
	}

	@Override
	public Object execute(JCL_task task) throws Exception {
		// TODO Auto-generated method stub
		return this.instantiate(task, task.getObjectClass());
	}

	@Override
	public void clearCache(String classID) {
		cache.remove(classID);
		cache1.remove(classID);
		
	}

	@Override
	public void clearCache() {
		// TODO Auto-generated method stub
		this.cache.clear();
		this.cache1.clear();
	}
	
	public static JCL_skeleton getInstance(){
		return Holder.instance;
	}
	
	private static class Holder{
		private static final JCL_skeleton instance = new JCL_skeletonImpl();
	}

}
